package com.clwl.supervise.superviseapp.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.clwl.supervise.superviseapp.entity.result.ResultEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;


@Slf4j
@ControllerAdvice
public class InterceptResponse implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {

        return true;
    }

    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        ServletServerHttpResponse responseTemp = (ServletServerHttpResponse) serverHttpResponse;
        HttpServletResponse resp = responseTemp.getServletResponse();
        resp.setContentType("application/json");
        //此处的 Result 对象是我自定义的返回值类型,具体根据自己需求修改即可
        if (body instanceof ResultEntity) {
            ResultEntity result = (ResultEntity) body;
            log.info("result类型:"+ ((result  == null || result.getData() == null) ? null:result.getData().getClass().getName()));
            if (result != null && result.getData() != null     ) {
                log.info("转换数据中的长度较长的数字");
                String s = result.getData() != null ? JSONObject.toJSONString(result.getData()) : "";
                //处理主键转换成字符串
                // s = s.replaceAll("\\d{10,20}$", "$0");
                if(JSONUtil.isJsonArray(s)){
                    //数组
                    result.setData(long2String(JSONArray.parseArray(s)));
                } else if(JSONUtil.isJson(s)){
                    result.setData(long2String(JSONObject.parseObject(s)));
                } else{
                    if(StringUtils.isNumeric(s)){
                        result.setData(s);
                    } else {
                        //不是数字则去除首位的"
                        s = StringUtils.removeEnd(s,"\"");
                        s = StringUtils.removeStart(s,"\"");
                        result.setData(s);
                    }
                }

                return result;
                //记录日志等操作
            }else{
                return body;
            }
            //这里可以对返回值进行修改二次封装等操作
        }else {
            return body;
        }
    }

    public JSONObject long2String(JSONObject jsonObject){
        if(jsonObject == null){
            return null;
        }
        Iterator iter = jsonObject.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();

            if(entry.getValue() instanceof JSONObject){
                long2String(jsonObject.getJSONObject(entry.getKey().toString()));
            }
            if(entry.getValue() instanceof JSONArray){
                JSONArray v = new JSONArray();
                try {
                    v = ((JSONArray) entry.getValue());
                } catch (Exception e) {
                    jsonObject.put(entry.getKey().toString(),entry.getValue());
                    continue;
                }
                try {
                    for (int i = 0; i < v.size(); i++) {
                        long2String(v.getJSONObject(i));
                    }
                } catch (Exception e) {
                    jsonObject.put(entry.getKey().toString(),entry.getValue());
                }
            }
            if(entry.getValue() instanceof Long){
                jsonObject.put(entry.getKey().toString(),ObjectUtil.toString(entry.getValue()));
            }

        }
        return jsonObject;
    }
    public JSONArray long2String(JSONArray jsonArray){
        JSONArray resultArray = new JSONArray();
        for (Object ob : jsonArray) {
            if(!(ob instanceof JSONObject)){
                resultArray.add(ob);
                continue;
            }
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(ob));
            Iterator iter = jsonObject.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                if(entry.getValue() instanceof JSONObject){
                    JSONObject jo =  long2String(jsonObject.getJSONObject(entry.getKey().toString()));
                    jsonObject.put(entry.getKey().toString(),jo);
                }
                if(entry.getValue() instanceof JSONArray){
                    JSONArray ja = new JSONArray();
                    for (int i = 0; i < ((JSONArray) entry.getValue()).size(); i++) {
                        if( !(entry.getValue() instanceof JSONArray)){
                            ja.add(entry.getValue());
                            continue;
                        }
                        try {
                            JSONObject jo = long2String(((JSONArray) entry.getValue()).getJSONObject(i));
                            ja.add(jo);
                        } catch (Exception e) {
                            ja.add( entry.getValue());
                        }
                    }
                    jsonObject.put(entry.getKey().toString(),ja);
                }
                if(entry.getValue() instanceof Long){
                    jsonObject.put(entry.getKey().toString(),ObjectUtil.toString(entry.getValue()));
                }
            }
            resultArray.add(jsonObject);
        }
        return resultArray;
    }
}

